﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;
using WinnerCMS.BLL;
using WinnerCMS.Common;
using WinnerCMS.Model;
using Field=Lucene.Net.Documents.Field;
namespace WinnerCMS.PlugIn.Indexer
{
    /*
     * API
     http://www.7-sun.com/doc/Lucene3.03/overview-summary.html
     */
    public sealed class IndexData : IDisposable
    {

        private readonly IndexWriter _writer;
        /// <summary>
        /// 索引目录
        /// </summary>
        public DirectoryInfo IndexDir { get; set; }
        /// <summary>
        /// 生成索引动作
        /// </summary>
        public IndexAction Action { get; set; }
        /// <summary>
        /// 多少一批
        /// </summary>
        public int LotSize { get; set; }
	

        public IndexData(string indexPath)
        {
            bool enableCreate = !System.IO.File.Exists(indexPath + "\\segments.gen");
             
            this.IndexDir = new DirectoryInfo(indexPath);
            var analyzer = new PanGuAnalyzer();
            this._writer = new IndexWriter(FSDirectory.Open(this.IndexDir), analyzer, false,
                IndexWriter.MaxFieldLength.LIMITED);

            _writer.SetMaxFieldLength(250000); //设置建立索引的长度，就是对数据的前多少条建立索引      
            _writer.SetMaxBufferedDocs(300); //控制写入一个新的segment前内存中保存的document的数目,设置较大的数目可以加快建索引速度     

        }



        #region

        public void ThreadIndexContent()
        {
            Thread th = new Thread(IndexContent)
            {
                IsBackground = true
            };
            th.Start();
        }

        /// <summary>
        ///  
        /// </summary>
        /// <returns></returns>
        public void IndexContent()
        {
            CacheHelper.Add("Index_Message", "正在组织任务列队", 3600);

            Console.WriteLine("索引开始启动");

            Fix();
            var list = new ModelManage().GetList();

            foreach (var mm in list.Where(x => x.Id == 2))
            {
                PagingParam pp = new PagingParam
                {
                    PageSize = LotSize,
                    RecordCount = new CoreManage().Count(mm)
                };
                Console.WriteLine("一共：" + pp.RecordCount + "条数据。");

                int totalpage = MyMath.GetCeiling(Convert.ToSingle(pp.RecordCount), Convert.ToSingle(pp.PageSize));

                //这两行代码纯粹为了测试需要。看是不是增量的
                
               
                for (int i = 1; i <= 1000; i++)
                {
                    pp.PageNo = i;
                    var cilist = new CoreManage().BindList(mm, pp);
                    DateTime start = DateTime.Now;
                    if (Action == IndexAction.AddOnly)
                    {
                        Parallel.ForEach(cilist, AddDocument);
                    }
                    else
                    {
                        Parallel.ForEach(cilist, UpdateDocument);
                    }

                     
                    Console.WriteLine("当前总索引数：" + _writer.NumDocs());
                    Console.WriteLine(i + "/" + totalpage + "，耗时" + (DateTime.Now - start).TotalSeconds);
                }
            }


            CacheHelper.Add("Index_Message", "正在优化索引", 3600);

            
            CacheHelper.Add("Index_Progress", list.Count, 100);

            CacheHelper.Remove("Index_Tatol");
            CacheHelper.Remove("Index_Progress");
            CacheHelper.Remove("Index_Message");
        }

        #endregion

        private void UpdateDocument(IContent model)
        {
            Term term = new Term("ID", model.Id.ToString());

            Document doc = new Document();
            doc.Add(new Lucene.Net.Documents.Field("ID", model.Id.ToString(), Field.Store.YES, Field.Index.NO));
            doc.Add(new Field("CategoryId", model.CategoryId.ToString(), Field.Store.YES, Field.Index.NO));
            doc.Add(new Field("ContentTitle", model.ContentTitle, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Content", HTML.NoHtml(model.Content), Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("UpdateTime", model.UpdateTime.ToString(), Field.Store.YES, Field.Index.NO));
            doc.Add(new Field("TemplateFileName", model.TemplateFileName, Field.Store.YES, Field.Index.NO));

            _writer.UpdateDocument(term, doc);
        }

        private void DeleteDocument(IContent model)
        {
            IndexReader reader = IndexReader.Open(FSDirectory.Open(this.IndexDir), false);

            Term term = new Term("ID", model.Id.ToString());
            reader.DeleteDocuments(term);
        }

        private void AddDocument(IContent model)
        {
            Document doc = new Document();
            doc.Add(new Field("ID", model.Id.ToString(), Field.Store.YES, Field.Index.NO));
            doc.Add(new Field("CategoryId", model.CategoryId.ToString(), Field.Store.YES, Field.Index.NO));
            doc.Add(new Field("ContentTitle", model.ContentTitle, Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("Content", HTML.NoHtml(model.Content), Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("UpdateTime", model.UpdateTime.ToString(), Field.Store.YES, Field.Index.NO));
            doc.Add(new Field("TemplateFileName", model.TemplateFileName, Field.Store.YES, Field.Index.NO));

            this._writer.AddDocument(doc);
        }

        /// <summary>
        /// Optimizes and save the index.
        /// </summary>
        private void Close()
        {
            if (!this._disposed)
            {
                _writer.Commit();
                _writer.Optimize();
                _writer.Dispose();
                this._disposed = true;
            }
        }

        private bool _disposed;

        public void Dispose()
        {
            Close();
        }

        /// <summary>
        /// 生成索引动作
        /// </summary>
        public enum IndexAction
        {
            AddOnly = 1,
            AddOrUpdate = 0
        }

        private void Fix()
        {
            if (this.LotSize == 0)
            {
                this.LotSize = 100;
            }
        }
    }


}